package com.yanqu.road.server.gameplayer.module.musicroom;

import com.yanqu.road.dao.impl.player.UserMusicRoomRankBeautyDaoImpl;
import com.yanqu.road.dao.impl.player.UserMusicRoomRankDaoImpl;
import com.yanqu.road.entity.activity.musicroomrank.MusicRoomRankConfigRankData;
import com.yanqu.road.entity.activity.musicroomrank.UserMusicRoomRankBeautyData;
import com.yanqu.road.entity.activity.musicroomrank.UserMusicRoomRankData;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogMusicRoomRankShowResult;
import com.yanqu.road.entity.musicroom.UserMusicRoomBeautyData;
import com.yanqu.road.entity.player.PlayerState;
import com.yanqu.road.entity.player.UserSkin;
import com.yanqu.road.logic.activity.musicroomrank.MusicRoomRankConfig;
import com.yanqu.road.pb.activity.MusicRoomRankProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.gameplayer.module.skin.SkinModule;
import com.yanqu.road.server.manger.activity.musicroomrank.MusicRoomRankActivityMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.pb.MusicRoomRankPb;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MusicRoomRankActivityModule extends GeneralModule {
    public MusicRoomRankActivityModule(GamePlayer player) {
        super(player);
    }

    private UserMusicRoomRankData userData = null;
    private Map<Integer, Map<Integer, UserMusicRoomRankBeautyData>> beautyDataMap = new ConcurrentHashMap<>();

    @Override
    public boolean loadData() {
        if (!MusicRoomRankActivityMgr.isInActivityShow()) {
            return true;
        }
        if (!isSystemUnlock()) {
            return true;
        }
        userData = new UserMusicRoomRankDaoImpl().getUserMusicRoomRankData(MusicRoomRankActivityMgr.getActivityId(), player.getUserId());
        beautyDataMap = new UserMusicRoomRankBeautyDaoImpl().getUserMusicRoomRankBeautyData(MusicRoomRankActivityMgr.getActivityId(), player.getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                new UserMusicRoomRankDaoImpl().add(userData);
            } else if (userData.isUpdateOption()) {
                new UserMusicRoomRankDaoImpl().update(userData);
            }
        }

        List<UserMusicRoomRankBeautyData> saveDataList = getSaveBeautyDataList();
        for (UserMusicRoomRankBeautyData beautyData : saveDataList) {
            if (beautyData.isInsertOption()) {
                new UserMusicRoomRankBeautyDaoImpl().add(beautyData);
            } else if (beautyData.isUpdateOption()) {
                new UserMusicRoomRankBeautyDaoImpl().update(beautyData);
            }
        }
        return true;
    }

    public void afterLogin() {
        initUserData();
        syncConfig();

        syncUserData();
        syncToCrossData();
    }

    public boolean isSystemUnlock() {
        return SystemOpenMgr.systemOpen(player, eSystemId.MusicRoomRank.getValue());
    }

    public void initSystemOpen() {
        initUserData();
        syncConfig();
        syncUserData();
    }

    public void initUserData() {
        if (!MusicRoomRankActivityMgr.isInActivityShow()) {
            return;
        }
        if (!isSystemUnlock()) {
            return;
        }
        if (userData == null || userData.getActivityId() != MusicRoomRankActivityMgr.getActivityId()) {
            userData = new UserMusicRoomRankData(MusicRoomRankActivityMgr.getActivityId(), getUserId());
            userData.setCardUseAmount(0);

            beautyDataMap.clear();
        }
    }

    public void syncConfig() {
        if (!MusicRoomRankActivityMgr.isInActivityShow()) {
            return;
        }
        if (!isSystemUnlock()) {
            return;
        }

        MusicRoomRankProto.MusicRoomRankConfigMsg.Builder configMsg = MusicRoomRankActivityMgr.getConfigMsg(player.getLanguage());
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_RANK_CONFIG_SYNC, configMsg);
    }


    public void syncUserData() {
        if (!MusicRoomRankActivityMgr.isInActivityShow()) {
            return;
        }
        if (!isSystemUnlock()) {
            return;
        }
        initUserData();

        MusicRoomRankProto.MusicRoomRankUserSyncMsg.Builder syncMsg = MusicRoomRankProto.MusicRoomRankUserSyncMsg.newBuilder();
        syncMsg.setActivityId(userData.getActivityId());
        syncMsg.setCardUseAmount(userData.getCardUseAmount());
        syncMsg.setLastJoinRound(userData.getLastJoinRound());
        syncMsg.setTotalScore(userData.getTotalScore());

        for (Map<Integer, UserMusicRoomRankBeautyData> dataMap : beautyDataMap.values()) {
            for (UserMusicRoomRankBeautyData beautyData : dataMap.values()) {
                syncMsg.addBeautyTemp(MusicRoomRankPb.parseBeautyTemp(beautyData));
            }
        }
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_RANK_USER_SYNC, syncMsg);


    }

    public void syncToCrossData() {
        //需求变动,不需要同步时辰卡使用数量到活动跨服
//        if (!MusicRoomRankActivityMgr.isInActivityShow()) {
//            return;
//        }
//        if (!isSystemUnlock()) {
//            return;
//        }
//        //同步时辰卡使用数量到活动跨服
//        if (userData.getCardUseAmount() > 0) {
//            MusicRoomRankProto.CrossMusicRoomRankSyncCardUsedMsg.Builder syncMsg = MusicRoomRankProto.CrossMusicRoomRankSyncCardUsedMsg.newBuilder();
//            syncMsg.setActivityId(MusicRoomRankActivityMgr.getActivityId());
//            syncMsg.setCardUseAmount(userData.getCardUseAmount());
//            player.sendPacket(CrossProtocol.C_MUSIC_ROOM_RANK_SYNC_CARD_USED, syncMsg);
//        }
    }

    /**
     * 请求主界面
     */
    public int getMainScene() {
        if (!MusicRoomRankActivityMgr.isInActivityTime()) {
            return GameErrorCode.E_ACTIVITY_NOT_OPEN;
        }
        if (!isSystemUnlock()) {
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        player.sendPacket(CrossProtocol.C_MUSIC_ROOM_RANK_MAIN_SCENE, MusicRoomRankProto.CrossMusicRoomRankMainSceneReqMsg.newBuilder().setActivityId(MusicRoomRankActivityMgr.getActivityId()));
        return 0;
    }

    /**
     * 请求历史榜单
     */
    public int getHistoryShowList() {
        if (!MusicRoomRankActivityMgr.isInActivityShow()) {
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        if (!isSystemUnlock()) {
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        player.sendPacket(CrossProtocol.C_MUSIC_ROOM_RANK_HISTORY_SHOW_LIST, MusicRoomRankProto.CrossMusicRoomRankHistoryShowListReqMsg.newBuilder().setActivityId(MusicRoomRankActivityMgr.getActivityId()));
        return 0;
    }

    /**
     * 请求历史榜单详情
     */
    public int getHistoryShowDetail(int round) {
        if (!MusicRoomRankActivityMgr.isInActivityShow()) {
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        if (!isSystemUnlock()) {
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        player.sendPacket(CrossProtocol.C_MUSIC_ROOM_RANK_HISTORY_SHOW_DETAIL, MusicRoomRankProto.CrossMusicRoomRankHistoryShowDetailReqMsg.newBuilder().setActivityId(MusicRoomRankActivityMgr.getActivityId()).setRound(round));
        return 0;
    }

    /**
     * 参赛
     */
    public int joinShow(MusicRoomRankProto.MusicRoomRankJoinShowReqMsg reqMsg) {
        synchronized (this) {
            if (!MusicRoomRankActivityMgr.isInActivityTime()) {
                return GameErrorCode.E_ACTIVITY_OVER_TIME;
            }
            if (!isSystemUnlock()) {
                return GameErrorCode.E_SYSTEM_NO_OPEN;
            }

            if (userData.getLastJoinRound() != 0) {
                //之前参赛的结果还没处理
                return GameErrorCode.E_MUSIC_ROOM_RANK_LAST_JOIN_NOT_HANDLE;
            }

            List<UserMusicRoomRankBeautyData> joinShowBeautyList = getJoinShowBeautyList();
            for (UserMusicRoomRankBeautyData beautyData : joinShowBeautyList) {
                if (beautyData.getJoinRound() != reqMsg.getRound()){
                    return GameErrorCode.E_MUSIC_ROOM_RANK_ROUND_END;
                }
            }

            MusicRoomRankConfig config = MusicRoomRankActivityMgr.getConfig();
            if(!config.isInOpenTime()){
                return GameErrorCode.E_ACTIVITY_NOT_OPEN;
            }

            int nowRoundJoinNum = getNowRoundJoinNum();
            if (nowRoundJoinNum >= config.getMaxUserBeautyNum()) {
                return GameErrorCode.E_MUSIC_ROOM_RANK_MAX_SHOW_BEAUTY_NUM;
            }

            Property cost = new Property();
            UserMusicRoomBeautyData musicRoomBeautyData = player.getModule(MusicRoomModule.class).getBeautyData(reqMsg.getBeautyId());
            if (musicRoomBeautyData == null) {
                return GameErrorCode.E_BEAUTY_NO_FOUND;
            }

            if (musicRoomBeautyData.getLiveInBuildId() == 0) {
                return GameErrorCode.E_MUSIC_ROOM_BEAUTY_NOT_LIVE_IN;
            }

            if (reqMsg.getSkinId() != 0) {
                UserSkin userSkin = player.getModule(SkinModule.class).getUserSkin(reqMsg.getSkinId());
                if (userSkin == null) {
                    return GameErrorCode.E_SKIN_NOT_EXIST;
                }
            }

            UserMusicRoomRankBeautyData beautyData = getBeautyData(reqMsg.getBeautyId(), reqMsg.getSkinId());
            if (beautyData == null) {
                beautyData = initBeautyData(reqMsg.getBeautyId(), reqMsg.getSkinId());
            }

            if (beautyData.getJoinRound() != 0) {
                return GameErrorCode.E_MUSIC_ROOM_RANK_REPEAT_JOIN;
            }

            if (beautyData.getFreeTimes() >= config.getFreeShowTimes()) {
                if (beautyData.getItemTimes() >= config.getItemShowTimes()) {
                    return GameErrorCode.E_MUSIC_ROOM_RANK_NOT_ITEM_TIMES;
                }
                cost.addProperty(config.getItemShowCost());
            }
            if (!cost.isNothing()) {
                if (!player.getModule(CurrencyModule.class).currencyIsEnough(cost)) {
                    return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                }

                player.getModule(PreReduceModule.class).preReduce(cost);
            }

            MusicRoomRankProto.CrossMusicRoomRankJoinShowReqMsg.Builder crossMsg = MusicRoomRankProto.CrossMusicRoomRankJoinShowReqMsg.newBuilder();
            crossMsg.setActivityId(MusicRoomRankActivityMgr.getActivityId());
            crossMsg.setBeautyId(reqMsg.getBeautyId());
            crossMsg.setSkinId(reqMsg.getSkinId());
            crossMsg.setUserBaseInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
            crossMsg.addAllAttrValue(musicRoomBeautyData.getRankAttrList());
            crossMsg.setCardUsedAmount(userData.getCardUseAmount());
            crossMsg.setRound(reqMsg.getRound());
            crossMsg.setCost(PropertyHelper.parsePropertyToString(cost));
            player.sendPacket(CrossProtocol.C_MUSIC_ROOM_RANK_JOIN_SHOW, crossMsg);
        }
        return 0;
    }

    public UserMusicRoomRankBeautyData getBeautyData(int beautyId, int skinId) {
        if (!beautyDataMap.containsKey(beautyId)) {
            return null;
        }
        return beautyDataMap.get(beautyId).get(skinId);
    }

    public UserMusicRoomRankBeautyData initBeautyData(int beautyId, int skinId) {
        synchronized (beautyDataMap) {
            if (!beautyDataMap.containsKey(beautyId)) {
                beautyDataMap.put(beautyId, new ConcurrentHashMap<>());
            }
            if (!beautyDataMap.get(beautyId).containsKey(skinId)) {
                beautyDataMap.get(beautyId).put(skinId, new UserMusicRoomRankBeautyData(MusicRoomRankActivityMgr.getActivityId(), getUserId(), beautyId, skinId));
            }
        }
        return beautyDataMap.get(beautyId).get(skinId);
    }

    private List<UserMusicRoomRankBeautyData> getSaveBeautyDataList() {
        List<UserMusicRoomRankBeautyData> beautyDataList = new ArrayList<>();
        for (Map<Integer, UserMusicRoomRankBeautyData> dataMap : beautyDataMap.values()) {
            for (UserMusicRoomRankBeautyData beautyData : dataMap.values()) {
                if (beautyData.isUpdateOption() || beautyData.isInsertOption()) {
                    //有参赛未结算的
                    beautyDataList.add(beautyData);
                }
            }
        }
        return beautyDataList;
    }

    public List<UserMusicRoomRankBeautyData> getJoinShowBeautyList() {
        synchronized (beautyDataMap) {
            List<UserMusicRoomRankBeautyData> beautyDataList = new ArrayList<>();
            for (Map<Integer, UserMusicRoomRankBeautyData> dataMap : beautyDataMap.values()) {
                for (UserMusicRoomRankBeautyData beautyData : dataMap.values()) {
                    if (beautyData.getJoinRound() != 0) {
                        //有参赛未结算的
                        beautyDataList.add(beautyData);
                    }
                }
            }
            return beautyDataList;
        }
    }

    public int getNowRoundJoinNum() {
        return getJoinShowBeautyList().size();
    }

    /**
     * 参赛返回处理
     *
     * @param backMsg
     */
    public void joinShowCrossBack(MusicRoomRankProto.CrossMusicRoomRankJoinShowBackMsg backMsg) {
        synchronized (this) {
            Property cost = new Property();
            if (!StringUtils.isNullOrEmpty(backMsg.getCost())) {
                cost = PropertyHelper.parseStringToProperty(backMsg.getCost());
            }
            if (!cost.isNothing()) {
                player.getModule(PreReduceModule.class).restorePreReduce(cost);
            }
            if (backMsg.getRet() > 0) {
                player.sendPacket(ClientProtocol.U_MUSIC_ROOM_RANK_JOIN_SHOW, MusicRoomRankProto.MusicRoomRankJoinShowRespMsg.newBuilder().setRet(backMsg.getRet()));
                return;
            }

            if (backMsg.getRet() == 0) {
                UserMusicRoomRankBeautyData beautyData = getBeautyData(backMsg.getBeautyId(), backMsg.getSkinId());
                beautyData.setJoinRound(backMsg.getRound());
                if (cost.isNothing()) {
                    beautyData.setFreeTimes(beautyData.getFreeTimes() + 1);
                } else {
                    player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.MusicRoomRank, eLogMoneyType.MusicRoomRankJoinShowCost);
                    beautyData.setItemTimes(beautyData.getItemTimes() + 1);
                }
            }

            player.sendPacket(ClientProtocol.U_MUSIC_ROOM_RANK_JOIN_SHOW, MusicRoomRankProto.MusicRoomRankJoinShowRespMsg.newBuilder().setRet(0));

            syncUserData();
        }
    }

    /**
     * 评选结果返回
     *
     * @param rankShowTempList
     * @param round
     */
    public void showResultCrossBack(List<MusicRoomRankProto.MusicRoomRankShowTemp> rankShowTempList, int round, int theme) {
        synchronized (this) {
            if (userData.getLastJoinRound() == round) {
                log.error("showResultCrossBack round not match userId:{} round:{} lastJoinRound:{}", getUserId(), round, userData.getLastJoinRound());
                return;
            }
            userData.setLastJoinRound(round);

            long scoreAdd = 0;
            for (MusicRoomRankProto.MusicRoomRankShowTemp rankShowTemp : rankShowTempList) {
                int beautyId = rankShowTemp.getBeautyId();
                int skinId = rankShowTemp.getSkinId();
                int rank = rankShowTemp.getIndex();
                long score = rankShowTemp.getRankScore();

                UserMusicRoomRankBeautyData beautyData = getBeautyData(beautyId, skinId);
                if (beautyData == null) {
                    log.error("showResultCrossBack beautyData is null userId:{} beautyId:{} skinId:{}", getUserId(), beautyId, skinId);
                    continue;
                }
                Property reward = new Property();
                beautyData.setShowRank(rank);
                beautyData.setShowScore(score);

                MusicRoomRankConfigRankData rankConfig = MusicRoomRankActivityMgr.getConfig().getRankConfigByRank(rank);
                if (rankConfig != null) {
                    reward = PropertyHelper.randomPropertyByListList(rankConfig.getRewardList());
                    beautyData.setShowReward(reward);
                }

                AutoLogMgr.add(new LogMusicRoomRankShowResult(userData.getActivityId(), getUserId(), round, beautyId, skinId, rankShowTemp.getCostType(), theme,
                        rankShowTemp.getScore(),
                        rankShowTemp.getRank(),
                        rankShowTemp.getRankScore(),
                        rankShowTemp.getBuffAddScore(),
                        PropertyHelper.parsePropertyToString(reward)));

                scoreAdd += score;
            }

            userData.setTotalScore(userData.getTotalScore() + scoreAdd);

            player.notifyListener(eGamePlayerEventType.MusicRoomScoreRank.getValue());

            if (player.getState() == PlayerState.ONLINE) {
                syncUserData();
            }
        }
    }

    /**
     * 评选结果处理,玩家请求主界面的时候调用
     */
    public int handleShowResult() {
        synchronized (this) {
            if (!MusicRoomRankActivityMgr.isInActivityShow()) {
                return GameErrorCode.E_ACTIVITY_OVER_TIME;
            }
            if (!isSystemUnlock()) {
                return GameErrorCode.E_SYSTEM_NO_OPEN;
            }
            if (userData.getLastJoinRound() == 0) {
                return GameErrorCode.E_MUSIC_ROOM_RANK_NOT_ROUND;
            }
            Property totalReward = new Property();
            long rankScoreAdd = 0;
            List<UserMusicRoomRankBeautyData> beautyList = getJoinShowBeautyList();
            for (UserMusicRoomRankBeautyData beautyData : beautyList) {
                rankScoreAdd += beautyData.getShowScore();
                totalReward.addProperty(beautyData.getShowReward());

                beautyData.resetJoin();
            }
            if (!totalReward.isNothing()) {
                player.getModule(CurrencyModule.class).addCurrency(totalReward, eLogMoneyType.MusicRoomRank, eLogMoneyType.MusicRoomRankJoinShowResultReward);
            }

            MusicRoomRankProto.MusicRoomRankHandleShowResultRespMsg.Builder clientMsg = MusicRoomRankProto.MusicRoomRankHandleShowResultRespMsg.newBuilder();
            clientMsg.setRet(0);
            clientMsg.setActivityId(MusicRoomRankActivityMgr.getActivityId());
            clientMsg.setRound(userData.getLastJoinRound());
            clientMsg.setReward(PropertyHelper.parsePropertyToString(totalReward));
            clientMsg.setRankScoreAdd(rankScoreAdd);
            player.sendPacket(ClientProtocol.U_MUSIC_ROOM_RANK_HANDLE_SHOW_RESULT, clientMsg);

            userData.setLastJoinRound(0);

            syncUserData();
        }

        return 0;
    }

    public void addCardUseAmount(int amount) {
        if (!MusicRoomRankActivityMgr.isInActivityTime()) {
            return;
        }
        if (!isSystemUnlock()) {
            return;
        }
        if (userData == null) {
            return;
        }

        long oldScore = getUserRankScore();

        userData.setCardUseAmount(userData.getCardUseAmount() + amount);
        syncUserData();
        syncToCrossData();

        long newScore = getUserRankScore();
        if (newScore > oldScore) {
            player.notifyListener(eGamePlayerEventType.MusicRoomScoreRank.getValue());
        }
    }

    public boolean checkBeautyWasJoin(int beautyId) {
        if (!MusicRoomRankActivityMgr.isInActivityTime()) {
            return false;
        }
        if (beautyDataMap.containsKey(beautyId)) {
            return true;
        }
        return false;
    }

    public long getUserRankScore() {
        if (userData == null) {
            return 0;
        }
        MusicRoomRankConfig config = MusicRoomRankActivityMgr.getConfig();
        if (config == null) {
            return 0;
        }
        long score = userData.getTotalScore();
        int cardUseAmountBuffValue = config.getCardUseAmountBuffValue(userData.getCardUseAmount());
        long newRankScore = BigDecimal.valueOf(score).multiply((BigDecimal.valueOf(cardUseAmountBuffValue + 1000).divide(BigDecimal.valueOf(1000)))).longValue();
        return newRankScore;
    }
}
